// Package kcp - A Fast and Reliable ARQ Protocol
package kcp

import (
	"container/heap"
	"encoding/binary"
	"sync/atomic"
)

const (
	IKCP_RTO_NDL     = 30  // no delay min rto
	IKCP_RTO_MIN     = 100 // normal min rto
	IKCP_RTO_DEF     = 200
	IKCP_RTO_MAX     = 60000
	IKCP_CMD_PUSH    = 81 // cmd: push data
	IKCP_CMD_ACK     = 82 // cmd: ack
	IKCP_CMD_WASK    = 83 // cmd: window probe (ask) 要求窗口探测
	IKCP_CMD_WINS    = 84 // cmd: window size (tell) 告诉窗口大小
	IKCP_ASK_SEND    = 1  // need to send IKCP_CMD_WASK WASK发送标记
	IKCP_ASK_TELL    = 2  // need to send IKCP_CMD_WINS WINS发送标记
	IKCP_WND_SND     = 32
	IKCP_WND_RCV     = 32
	IKCP_MTU_DEF     = 1400
	IKCP_ACK_FAST    = 3
	IKCP_INTERVAL    = 100
	IKCP_OVERHEAD    = 24
	IKCP_DEADLINK    = 20
	IKCP_THRESH_INIT = 2
	IKCP_THRESH_MIN  = 2
	IKCP_PROBE_INIT  = 7000   // 7 secs to probe window size
	IKCP_PROBE_LIMIT = 120000 // up to 120 secs to probe window
)

// Output is a closure which captures conn and calls conn.Write
type Output func(buf []byte, size int)

/* encode 8 bits unsigned int */
func ikcp_encode8u(p []byte, c byte) []byte {
	p[0] = c
	return p[1:]
}

/* decode 8 bits unsigned int */
func ikcp_decode8u(p []byte, c *byte) []byte {
	*c = p[0]
	return p[1:]
}

/* encode 16 bits unsigned int (lsb) */
func ikcp_encode16u(p []byte, w uint16) []byte {
	binary.LittleEndian.PutUint16(p, w)
	return p[2:]
}

/* decode 16 bits unsigned int (lsb) */
func ikcp_decode16u(p []byte, w *uint16) []byte {
	*w = binary.LittleEndian.Uint16(p)
	return p[2:]
}

/* encode 32 bits unsigned int (lsb) */
func ikcp_encode32u(p []byte, l uint32) []byte {
	binary.LittleEndian.PutUint32(p, l)
	return p[4:]
}

/* decode 32 bits unsigned int (lsb) */
func ikcp_decode32u(p []byte, l *uint32) []byte {
	*l = binary.LittleEndian.Uint32(p)
	return p[4:]
}

func _imin_(a, b uint32) uint32 {
	if a <= b {
		return a
	} else {
		return b
	}
}

func _imax_(a, b uint32) uint32 {
	if a >= b {
		return a
	} else {
		return b
	}
}

func _ibound_(lower, middle, upper uint32) uint32 {
	return _imin_(_imax_(lower, middle), upper)
}

func _itimediff(later, earlier uint32) int32 {
	return (int32)(later - earlier)
}

// Segment defines a KCP segment
type Segment struct {
	conv     uint32		//连接id
	cmd      uint32		//命令类型
	frg      uint32		//一个message拆成多个Segment时，使用fragment进行编号.message mode时有效，编号从大到小；无效时为0
	wnd      uint32		//窗口大小。？用途
	ts       uint32		//时间戳
	sn       uint32		//seg的编号。产生策略，由kcp维护，从0开始增长
	una      uint32		//ack对应包的sn号
	resendts uint32		//？重发时间戳
	rto      uint32		//主机从发出数据包到第一次TCP重传开始，RFC中这段时间间隔称为retransmission timeout，缩写做RTO
	fastack  uint32		//快速重传标记。？触发重传后被重置为0
	xmit     uint32		//总发送次数
	data     []byte		//要发送的数据
}

// encode a segment into buffer
func (seg *Segment) encode(ptr []byte) []byte {
	ptr = ikcp_encode32u(ptr, seg.conv)
	ptr = ikcp_encode8u(ptr, uint8(seg.cmd))
	ptr = ikcp_encode8u(ptr, uint8(seg.frg))
	ptr = ikcp_encode16u(ptr, uint16(seg.wnd))
	ptr = ikcp_encode32u(ptr, seg.ts)
	ptr = ikcp_encode32u(ptr, seg.sn)
	ptr = ikcp_encode32u(ptr, seg.una)
	ptr = ikcp_encode32u(ptr, uint32(len(seg.data)))
	return ptr
}

// NewSegment creates a KCP segment
func NewSegment(size int) *Segment {
	seg := new(Segment)
	seg.data = make([]byte, size)
	return seg
}

// KCP defines a single KCP connection
type KCP struct {
	conv, mtu, mss, state                  uint32	//conv:会话编号 MTU:Maxitum Transmission Unit 最大传输单元 MSS:Maxitum Segment Size 最大分段大小，单个seg最大数据长度 state:会话状态
	snd_una, snd_nxt, rcv_nxt              uint32	//snd_una:已收到ack的序号 rc_nxt:下一个要接收的序号 snd_nxt:下一个要发送的序号
	ssthresh                               uint32	//ssthresh:慢启动阈值
	rx_rttval, rx_srtt, rx_rto, rx_minrto  uint32	//srtt为经过平滑后的RTT值，它代表着当前的RTT值，每收到一个ACK更新一次。
	snd_wnd, rcv_wnd, rmt_wnd, cwnd, probe uint32	//snd_wnd:发送窗口 rcv_wnd:接收窗口 rmt_wnd:对端窗口 cwnd:拥塞窗口 probe:探测标记
	current, interval, ts_flush, xmit      uint32	//current:当前时间,毫秒 interval:数据发送周期 ts_flush:数据flush时间戳  xmit:总重发次数
	nodelay, updated                       uint32	//nodelay:？无延迟 updated:Update是否被调用过
	ts_probe, probe_wait                   uint32	//tc_probe:窗口探测时间戳 probe_wait:窗口探测间隔，远程窗口变为0之后，等待probe_wait的时间，然后探测窗口是否可用。
	dead_link, incr                        uint32	//dead_link:最大重发次数 incr:

	fastresend     int32
	nocwnd, stream int32

	snd_queue []Segment	//待发送队列
	rcv_queue []Segment	//接收队列
	snd_buf   []Segment	//已发送包缓冲区
	rcv_buf   []Segment	//已接收包缓冲区

	acklist ackList		//ack列表

	buffer []byte		//会话数据缓冲区
	output Output		//回调接口
}

type ackItem struct {
	sn uint32	//被ack的包编号
	ts uint32	//时间戳
}

type ackList []ackItem

func (l ackList) Len() int            { return len(l) }
func (l ackList) Less(i, j int) bool  { return l[i].sn < l[j].sn }
func (l ackList) Swap(i, j int)       { l[i], l[j] = l[j], l[i] }
func (l *ackList) Push(x interface{}) { *l = append(*l, x.(ackItem)) }
func (l *ackList) Pop() interface{} {
	old := *l
	n := len(old)
	x := old[n-1]
	*l = old[0 : n-1]
	return x
}

// NewKCP create a new kcp control object, 'conv' must equal in two endpoint
// from the same connection.
func NewKCP(conv uint32, output Output) *KCP {
	kcp := new(KCP)
	kcp.conv = conv
	kcp.snd_wnd = IKCP_WND_SND
	kcp.rcv_wnd = IKCP_WND_RCV
	kcp.rmt_wnd = IKCP_WND_RCV
	kcp.mtu = IKCP_MTU_DEF
	kcp.mss = kcp.mtu - IKCP_OVERHEAD
	kcp.buffer = make([]byte, (kcp.mtu+IKCP_OVERHEAD)*3)
	kcp.rx_rto = IKCP_RTO_DEF
	kcp.rx_minrto = IKCP_RTO_MIN
	kcp.interval = IKCP_INTERVAL
	kcp.ts_flush = IKCP_INTERVAL
	kcp.ssthresh = IKCP_THRESH_INIT
	kcp.dead_link = IKCP_DEADLINK
	kcp.output = output
	return kcp
}

// PeekSize checks the size of next message in the recv queue
func (kcp *KCP) PeekSize() (length int) {
	if len(kcp.rcv_queue) == 0 {
		return -1
	}

	seg := &kcp.rcv_queue[0]
	if seg.frg == 0 {
		return len(seg.data)
	}

	if len(kcp.rcv_queue) < int(seg.frg+1) {
		return -1
	}

	for k := range kcp.rcv_queue {
		seg := &kcp.rcv_queue[k]
		length += len(seg.data)
		if seg.frg == 0 {
			break
		}
	}
	return
}

// Recv is user/upper level recv: returns size, returns below zero for EAGAIN
func (kcp *KCP) Recv(buffer []byte) (n int) {
	if len(kcp.rcv_queue) == 0 {
		return -1
	}

	peeksize := kcp.PeekSize()
	if peeksize < 0 {
		return -2
	}

	if peeksize > len(buffer) {
		return -3
	}

	var fast_recover bool
	if len(kcp.rcv_queue) >= int(kcp.rcv_wnd) {
		fast_recover = true
	}

	// merge fragment
	count := 0
	for k := range kcp.rcv_queue {
		seg := &kcp.rcv_queue[k]
		copy(buffer, seg.data)
		buffer = buffer[len(seg.data):]
		n += len(seg.data)
		count++
		seg.data = nil
		if seg.frg == 0 {
			break
		}
	}
	kcp.rcv_queue = kcp.rcv_queue[count:]

	// move available data from rcv_buf -> rcv_queue
	count = 0
	for k := range kcp.rcv_buf {
		seg := &kcp.rcv_buf[k]
		if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
			kcp.rcv_queue = append(kcp.rcv_queue, *seg)
			kcp.rcv_nxt++
			count++
			seg.data = nil
		} else {
			break
		}
	}
	kcp.rcv_buf = kcp.rcv_buf[count:]

	// fast recover
	if len(kcp.rcv_queue) < int(kcp.rcv_wnd) && fast_recover { // 窗口变动，通知对端
		// ready to send back IKCP_CMD_WINS in ikcp_flush
		// tell remote my window size
		kcp.probe |= IKCP_ASK_TELL
	}
	return
}

// Send is user/upper level send, returns below zero for error
func (kcp *KCP) Send(buffer []byte) int {	//发送数据。将数据按mss分成seg，放入snd_queue
	var count int
	if len(buffer) == 0 {
		return -1
	}

	// append to previous segment in streaming mode (if possible)
	if kcp.stream != 0 {
		n := len(kcp.snd_queue)
		if n > 0 {
			old := &kcp.snd_queue[n-1]
			if len(old.data) < int(kcp.mss) {
				capacity := int(kcp.mss) - len(old.data)
				extend := capacity
				if len(buffer) < capacity {
					extend = len(buffer)
				}
				seg := NewSegment(len(old.data) + extend)
				seg.frg = 0
				copy(seg.data, old.data)
				copy(seg.data[len(old.data):], buffer)
				buffer = buffer[extend:]
				kcp.snd_queue[n-1] = *seg
			}
		}

		if len(buffer) == 0 {
			return 0
		}
	}

	if len(buffer) <= int(kcp.mss) {
		count = 1
	} else {
		count = (len(buffer) + int(kcp.mss) - 1) / int(kcp.mss)
	}

	if count > 255 { //数据量不能超过 mss*255
		return -2
	}

	if count == 0 {
		count = 1
	}

	for i := 0; i < count; i++ {
		var size int
		if len(buffer) > int(kcp.mss) {
			size = int(kcp.mss)
		} else {
			size = len(buffer)
		}
		seg := NewSegment(size)
		copy(seg.data, buffer[:size])
		if kcp.stream == 0 { // message mode
			seg.frg = uint32(count - i - 1) //frg从大到小排，只有message mode 有效
		} else { // stream mode
			seg.frg = 0
		}
		kcp.snd_queue = append(kcp.snd_queue, *seg)
		buffer = buffer[size:]
	}
	return 0
}

// https://tools.ietf.org/html/rfc6298
func (kcp *KCP) update_ack(rtt int32) { //更新超时控制相关参数
	var rto uint32
	if kcp.rx_srtt == 0 {
		kcp.rx_srtt = uint32(rtt)
		kcp.rx_rttval = uint32(rtt) / 2
	} else {
		delta := rtt - int32(kcp.rx_srtt)
		if delta < 0 {
			delta = -delta
		}
		kcp.rx_rttval = (3*kcp.rx_rttval + uint32(delta)) / 4
		kcp.rx_srtt = (7*kcp.rx_srtt + uint32(rtt)) / 8
		if kcp.rx_srtt < 1 {
			kcp.rx_srtt = 1
		}
	}
	rto = kcp.rx_srtt + _imax_(1, 4*kcp.rx_rttval)
	kcp.rx_rto = _ibound_(kcp.rx_minrto, rto, IKCP_RTO_MAX)
}

func (kcp *KCP) shrink_buf() { //调整snd_una的指
	if len(kcp.snd_buf) > 0 { //发送缓存不为空
		seg := &kcp.snd_buf[0]
		kcp.snd_una = seg.sn
	} else {
		kcp.snd_una = kcp.snd_nxt
	}
}

func (kcp *KCP) parse_ack(sn uint32) {
	if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 {
		return
	}

	for k := range kcp.snd_buf {
		seg := &kcp.snd_buf[k]
		if sn == seg.sn {
			copy(kcp.snd_buf[k:], kcp.snd_buf[k+1:])
			kcp.snd_buf[len(kcp.snd_buf)-1] = Segment{}
			kcp.snd_buf = kcp.snd_buf[:len(kcp.snd_buf)-1]
			break
		}
		if _itimediff(sn, seg.sn) < 0 {
			break
		}
	}
}

func (kcp *KCP) parse_fastack(sn uint32) {
	if _itimediff(sn, kcp.snd_una) < 0 || _itimediff(sn, kcp.snd_nxt) >= 0 {
		return
	}

	for k := range kcp.snd_buf { //ack收到一个大号码，则此号码之前被跳过的号码，标记为fastack，每跳过一次增加1.
		seg := &kcp.snd_buf[k]
		if _itimediff(sn, seg.sn) < 0 {
			break
		} else if sn != seg.sn { //  && kcp.current >= seg.ts+kcp.rx_srtt {
			seg.fastack++
		}
	}
}

func (kcp *KCP) parse_una(una uint32) { //una为对方已确认收到的序号，根据该序号，清理发送缓冲区中已发送成功的数据。
	count := 0
	for k := range kcp.snd_buf {
		seg := &kcp.snd_buf[k]
		if _itimediff(una, seg.sn) > 0 {
			count++
			seg.data = nil
		} else {
			break
		}
	}
	kcp.snd_buf = kcp.snd_buf[count:]
}

// ack append
func (kcp *KCP) ack_push(sn, ts uint32) {
	heap.Push(&kcp.acklist, ackItem{sn, ts})
}

func (kcp *KCP) parse_data(newseg *Segment) {
	sn := newseg.sn
	if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) >= 0 ||
		_itimediff(sn, kcp.rcv_nxt) < 0 {
		atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
		return
	}

	n := len(kcp.rcv_buf) - 1
	insert_idx := 0
	repeat := false
	for i := n; i >= 0; i-- {
		seg := &kcp.rcv_buf[i]
		if seg.sn == sn {
			repeat = true
			atomic.AddUint64(&DefaultSnmp.RepeatSegs, 1)
			break
		}
		if _itimediff(sn, seg.sn) > 0 {
			insert_idx = i + 1
			break
		}
	}

	if !repeat {
		if insert_idx == n+1 {
			kcp.rcv_buf = append(kcp.rcv_buf, *newseg) //插在尾部
		} else {	//插在中间，部分后移
			kcp.rcv_buf = append(kcp.rcv_buf, Segment{})
			copy(kcp.rcv_buf[insert_idx+1:], kcp.rcv_buf[insert_idx:])
			kcp.rcv_buf[insert_idx] = *newseg
		}
	}

	// move available data from rcv_buf -> rcv_queue
	count := 0
	for k := range kcp.rcv_buf {
		seg := &kcp.rcv_buf[k]
		if seg.sn == kcp.rcv_nxt && len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
			kcp.rcv_queue = append(kcp.rcv_queue, kcp.rcv_buf[k])
			kcp.rcv_nxt++
			count++
			seg.data = nil
		} else {
			break
		}
	}
	kcp.rcv_buf = kcp.rcv_buf[count:]
}

// Input when you received a low level packet (eg. UDP packet), call it
func (kcp *KCP) Input(data []byte, update_ack bool) int {
	old_una := kcp.snd_una
	if len(data) < IKCP_OVERHEAD {
		return -1
	}

	var maxack uint32
	var flag int
	for {
		var ts, sn, length, una, conv uint32
		var wnd uint16
		var cmd, frg uint8

		if len(data) < int(IKCP_OVERHEAD) {
			break
		}

		data = ikcp_decode32u(data, &conv)
		if conv != kcp.conv { //前后一致的connection id
			return -1
		}

		data = ikcp_decode8u(data, &cmd)
		data = ikcp_decode8u(data, &frg)
		data = ikcp_decode16u(data, &wnd)
		data = ikcp_decode32u(data, &ts)
		data = ikcp_decode32u(data, &sn)
		data = ikcp_decode32u(data, &una)
		data = ikcp_decode32u(data, &length)
		if len(data) < int(length) {
			return -2
		}

		if cmd != IKCP_CMD_PUSH && cmd != IKCP_CMD_ACK &&
			cmd != IKCP_CMD_WASK && cmd != IKCP_CMD_WINS {
			return -3
		}

		kcp.rmt_wnd = uint32(wnd) //对端窗口大小
		kcp.parse_una(una)
		kcp.shrink_buf()

		if cmd == IKCP_CMD_ACK {
			if update_ack && _itimediff(kcp.current, ts) >= 0 {
				kcp.update_ack(_itimediff(kcp.current, ts))
			}
			kcp.parse_ack(sn)
			kcp.shrink_buf()
			if flag == 0 {
				flag = 1
				maxack = sn
			} else if _itimediff(sn, maxack) > 0 {
				maxack = sn //maxack最终记录的ack中号码最大的
			}
		} else if cmd == IKCP_CMD_PUSH {
			if _itimediff(sn, kcp.rcv_nxt+kcp.rcv_wnd) < 0 {
				kcp.ack_push(sn, ts)
				if _itimediff(sn, kcp.rcv_nxt) >= 0 {
					seg := NewSegment(int(length))
					seg.conv = conv
					seg.cmd = uint32(cmd)
					seg.frg = uint32(frg)
					seg.wnd = uint32(wnd)
					seg.ts = ts
					seg.sn = sn
					seg.una = una
					copy(seg.data, data[:length])
					kcp.parse_data(seg)
				}
			}
		} else if cmd == IKCP_CMD_WASK {
			// ready to send back IKCP_CMD_WINS in Ikcp_flush
			// tell remote my window size
			kcp.probe |= IKCP_ASK_TELL
		} else if cmd == IKCP_CMD_WINS {
			// do nothing
		} else {
			return -3
		}

		data = data[length:]
	}

	if flag != 0 && update_ack { //收到的数据中包含ack,对snd_buf中的数据，标记fastact
		kcp.parse_fastack(maxack)
	}
	//http://www.cnblogs.com/zszmhd/p/3623155.html
	if _itimediff(kcp.snd_una, old_una) > 0 { //收到有效的ack，意味着远端窗口产生变动,慢启动处理
		if kcp.cwnd < kcp.rmt_wnd { //拥塞窗口 小于 远端窗口
			mss := kcp.mss
			if kcp.cwnd < kcp.ssthresh {
				kcp.cwnd++
				kcp.incr += mss
			} else {
				if kcp.incr < mss {
					kcp.incr = mss
				}
				kcp.incr += (mss*mss)/kcp.incr + (mss / 16)
				if (kcp.cwnd+1)*mss <= kcp.incr {
					kcp.cwnd++
				}
			}
			if kcp.cwnd > kcp.rmt_wnd {
				kcp.cwnd = kcp.rmt_wnd
				kcp.incr = kcp.rmt_wnd * mss
			}
		}
	}

	return 0
}

func (kcp *KCP) wnd_unused() int32 { //可用的接收窗口大小
	if len(kcp.rcv_queue) < int(kcp.rcv_wnd) {
		return int32(int(kcp.rcv_wnd) - len(kcp.rcv_queue))
	}
	return 0
}

// flush pending data
func (kcp *KCP) flush() {
	current := kcp.current
	buffer := kcp.buffer
	change := 0
	lost := false

	if kcp.updated == 0 {
		return
	}
	var seg Segment
	seg.conv = kcp.conv
	seg.cmd = IKCP_CMD_ACK
	seg.wnd = uint32(kcp.wnd_unused())
	seg.una = kcp.rcv_nxt

	// flush acknowledges 先把ack处理完
	ptr := buffer
	for kcp.acklist.Len() > 0 {
		size := len(buffer) - len(ptr)
		if size+IKCP_OVERHEAD > int(kcp.mtu) {
			kcp.output(buffer, size)
			ptr = buffer
		}
		ack := heap.Pop(&kcp.acklist).(ackItem)
		seg.sn, seg.ts = ack.sn, ack.ts
		ptr = seg.encode(ptr)
	}
	kcp.acklist = nil

	// probe window size (if remote window size equals zero)
	if kcp.rmt_wnd == 0 { //如果对端窗口大小为0，则设定ts_probe,到了ts_probe定义的时间之后，发送IKCP_CMD_WASK
		if kcp.probe_wait == 0 {
			kcp.probe_wait = IKCP_PROBE_INIT
			kcp.ts_probe = kcp.current + kcp.probe_wait
		} else {
			if _itimediff(kcp.current, kcp.ts_probe) >= 0 { //如果对端窗口大小一直为0。则不断增大probe_wait的值，即放慢探测节奏。
				if kcp.probe_wait < IKCP_PROBE_INIT {
					kcp.probe_wait = IKCP_PROBE_INIT
				}
				kcp.probe_wait += kcp.probe_wait / 2
				if kcp.probe_wait > IKCP_PROBE_LIMIT {
					kcp.probe_wait = IKCP_PROBE_LIMIT
				}
				kcp.ts_probe = kcp.current + kcp.probe_wait
				kcp.probe |= IKCP_ASK_SEND
			}
		}
	} else {	//当对端窗口大于0，重置tc_probe和probe_wait为0.
		kcp.ts_probe = 0
		kcp.probe_wait = 0
	}

	// flush window probing commands
	if (kcp.probe & IKCP_ASK_SEND) != 0 { //如果有wask发送标记，则发送wask命令
		seg.cmd = IKCP_CMD_WASK
		size := len(buffer) - len(ptr)
		if size+IKCP_OVERHEAD > int(kcp.mtu) {
			kcp.output(buffer, size)
			ptr = buffer
		}
		ptr = seg.encode(ptr)
	}

	// flush window probing commands
	if (kcp.probe & IKCP_ASK_TELL) != 0 { //如果有wins发送标记，则发送wins命令
		seg.cmd = IKCP_CMD_WINS
		size := len(buffer) - len(ptr)
		if size+IKCP_OVERHEAD > int(kcp.mtu) {
			kcp.output(buffer, size)
			ptr = buffer
		}
		ptr = seg.encode(ptr)
	}

	kcp.probe = 0	//重置窗口探测标记

	// calculate window size
	cwnd := _imin_(kcp.snd_wnd, kcp.rmt_wnd) //取发送窗口 和 远程窗口中最小的值，作为 计算窗口
	if kcp.nocwnd == 0 {
		cwnd = _imin_(kcp.cwnd, cwnd)
	}

	count := 0
	for k := range kcp.snd_queue {	//遍历发送队列
		if _itimediff(kcp.snd_nxt, kcp.snd_una+cwnd) >= 0 { //超出窗口大小，则终止发送
			break
		}
		newseg := kcp.snd_queue[k]
		newseg.conv = kcp.conv
		newseg.cmd = IKCP_CMD_PUSH
		newseg.wnd = seg.wnd
		newseg.ts = current
		newseg.sn = kcp.snd_nxt
		newseg.una = kcp.rcv_nxt
		newseg.resendts = current
		newseg.rto = kcp.rx_rto
		newseg.fastack = 0
		newseg.xmit = 0
		kcp.snd_buf = append(kcp.snd_buf, newseg) //将要发送的数据，放入发送缓冲区
		kcp.snd_nxt++	//自增 下一个发送序号
		count++
		kcp.snd_queue[k].data = nil	//引用置空
	}
	kcp.snd_queue = kcp.snd_queue[count:]	//从发送队列中丢弃已发送数据

	// calculate resent
	resent := uint32(kcp.fastresend)
	if kcp.fastresend <= 0 {
		resent = 0xffffffff
	}
	rtomin := (kcp.rx_rto >> 3)
	if kcp.nodelay != 0 {
		rtomin = 0
	}

	// flush data segments
	nque := len(kcp.snd_queue) //待发送队列剩余长度
	var lostSegs, fastRetransSegs, earlyRetransSegs uint64
	for k := range kcp.snd_buf { //遍历发送缓冲
		segment := &kcp.snd_buf[k]
		needsend := false
		if segment.xmit == 0 { //该segment总发送次数为0，立即发送
			needsend = true
			segment.xmit++
			segment.rto = kcp.rx_rto
			segment.resendts = current + segment.rto + rtomin //重发时间戳
		} else if _itimediff(current, segment.resendts) >= 0 { //当前时间超过重发时间戳，立即发送
			needsend = true
			segment.xmit++
			kcp.xmit++
			if kcp.nodelay == 0 { //如果delay，rto扩大2倍
				segment.rto += kcp.rx_rto
			} else {//如果nodelay，rto扩大1.5倍
				segment.rto += kcp.rx_rto / 2
			}
			segment.resendts = current + segment.rto //设置重发时间戳
			lost = true //丢包
			lostSegs++ //丢包+1
		} else if segment.fastack >= resent { //超过快速重传设定的值，立即发送
			needsend = true
			segment.xmit++
			segment.fastack = 0
			segment.resendts = current + segment.rto
			change++ //?
			fastRetransSegs++ //快速重传+1
		} else if segment.fastack > 0 && nque == 0 { //如果发送队列剩余数据为空，且faskack被标记，则提前发起重传
			// early retransmit
			needsend = true
			segment.xmit++
			segment.fastack = 0
			segment.resendts = current + segment.rto
			change++ //?
			earlyRetransSegs++ //提前重传+1
		}

		if needsend { //如果需要发送，则发送数据
			segment.ts = current
			segment.wnd = seg.wnd
			segment.una = kcp.rcv_nxt

			size := len(buffer) - len(ptr)
			need := IKCP_OVERHEAD + len(segment.data)

			if size+need > int(kcp.mtu) {
				kcp.output(buffer, size)
				ptr = buffer
			}

			ptr = segment.encode(ptr)
			copy(ptr, segment.data)
			ptr = ptr[len(segment.data):]

			if segment.xmit >= kcp.dead_link {
				kcp.state = 0xFFFFFFFF
			}
		}
	}

	atomic.AddUint64(&DefaultSnmp.RetransSegs, lostSegs+fastRetransSegs+earlyRetransSegs)
	atomic.AddUint64(&DefaultSnmp.LostSegs, lostSegs)
	atomic.AddUint64(&DefaultSnmp.EarlyRetransSegs, earlyRetransSegs)
	atomic.AddUint64(&DefaultSnmp.FastRetransSegs, fastRetransSegs)

	// flash remain segments 如果剩余的还有数据，立即发送
	size := len(buffer) - len(ptr)
	if size > 0 {
		kcp.output(buffer, size)
	}

	// update ssthresh
	// rate halving, https://tools.ietf.org/html/rfc6937
	if change != 0 {
		inflight := kcp.snd_nxt - kcp.snd_una
		kcp.ssthresh = inflight / 2
		if kcp.ssthresh < IKCP_THRESH_MIN {
			kcp.ssthresh = IKCP_THRESH_MIN
		}
		kcp.cwnd = kcp.ssthresh + resent
		kcp.incr = kcp.cwnd * kcp.mss
	}

	// congestion control, https://tools.ietf.org/html/rfc5681
	if lost {
		kcp.ssthresh = cwnd / 2
		if kcp.ssthresh < IKCP_THRESH_MIN {
			kcp.ssthresh = IKCP_THRESH_MIN
		}
		kcp.cwnd = 1
		kcp.incr = kcp.mss
	}

	if kcp.cwnd < 1 {
		kcp.cwnd = 1
		kcp.incr = kcp.mss
	}
}

// Update updates state (call it repeatedly, every 10ms-100ms), or you can ask
// ikcp_check when to call it again (without ikcp_input/_send calling).
// 'current' - current timestamp in millisec.
func (kcp *KCP) Update(current uint32) { //按照间隔interval，对flush进行调用。
	var slap int32

	kcp.current = current

	if kcp.updated == 0 { //第一次更新时间时被调用，只被调用一次。
		kcp.updated = 1
		kcp.ts_flush = kcp.current
	}

	slap = _itimediff(kcp.current, kcp.ts_flush)

	if slap >= 10000 || slap < -10000 {
		kcp.ts_flush = kcp.current
		slap = 0
	}

	if slap >= 0 {//正常情况下，每隔interval时间flush一次，interval默认100毫秒
		kcp.ts_flush += kcp.interval
		if _itimediff(kcp.current, kcp.ts_flush) >= 0 {
			kcp.ts_flush = kcp.current + kcp.interval
		}
		kcp.flush()
	}
}

// Check determines when should you invoke ikcp_update:
// returns when you should invoke ikcp_update in millisec, if there
// is no ikcp_input/_send calling. you can call ikcp_update in that
// time, instead of call update repeatly.
// Important to reduce unnacessary ikcp_update invoking. use it to
// schedule ikcp_update (eg. implementing an epoll-like mechanism,
// or optimize ikcp_update when handling massive kcp connections)
func (kcp *KCP) Check(current uint32) uint32 {
	ts_flush := kcp.ts_flush
	tm_flush := int32(0x7fffffff)
	tm_packet := int32(0x7fffffff)
	minimal := uint32(0)
	if kcp.updated == 0 {
		return current
	}

	if _itimediff(current, ts_flush) >= 10000 ||
		_itimediff(current, ts_flush) < -10000 {
		ts_flush = current
	}

	if _itimediff(current, ts_flush) >= 0 {
		return current
	}

	tm_flush = _itimediff(ts_flush, current)

	for k := range kcp.snd_buf {
		seg := &kcp.snd_buf[k]
		diff := _itimediff(seg.resendts, current)
		if diff <= 0 {
			return current
		}
		if diff < tm_packet {
			tm_packet = diff
		}
	}

	minimal = uint32(tm_packet)
	if tm_packet >= tm_flush {
		minimal = uint32(tm_flush)
	}
	if minimal >= kcp.interval {
		minimal = kcp.interval
	}

	return current + minimal
}

// SetMtu changes MTU size, default is 1400
func (kcp *KCP) SetMtu(mtu int) int {
	if mtu < 50 || mtu < IKCP_OVERHEAD {
		return -1
	}
	buffer := make([]byte, (mtu+IKCP_OVERHEAD)*3)
	if buffer == nil {
		return -2
	}
	kcp.mtu = uint32(mtu)
	kcp.mss = kcp.mtu - IKCP_OVERHEAD
	kcp.buffer = buffer
	return 0
}

// NoDelay options
// fastest: ikcp_nodelay(kcp, 1, 20, 2, 1)
// nodelay: 0:disable(default), 1:enable
// interval: internal update timer interval in millisec, default is 100ms
// resend: 0:disable fast resend(default), 1:enable fast resend
// nc: 0:normal congestion control(default), 1:disable congestion control
func (kcp *KCP) NoDelay(nodelay, interval, resend, nc int) int {
	if nodelay >= 0 {
		kcp.nodelay = uint32(nodelay)
		if nodelay != 0 {
			kcp.rx_minrto = IKCP_RTO_NDL
		} else {
			kcp.rx_minrto = IKCP_RTO_MIN
		}
	}
	if interval >= 0 {
		if interval > 5000 {
			interval = 5000
		} else if interval < 10 {
			interval = 10
		}
		kcp.interval = uint32(interval)
	}
	if resend >= 0 {
		kcp.fastresend = int32(resend)
	}
	if nc >= 0 {
		kcp.nocwnd = int32(nc)
	}
	return 0
}

// WndSize sets maximum window size: sndwnd=32, rcvwnd=32 by default
func (kcp *KCP) WndSize(sndwnd, rcvwnd int) int {
	if sndwnd > 0 {
		kcp.snd_wnd = uint32(sndwnd)
	}
	if rcvwnd > 0 {
		kcp.rcv_wnd = uint32(rcvwnd)
	}
	return 0
}

// WaitSnd gets how many packet is waiting to be sent
func (kcp *KCP) WaitSnd() int {
	return len(kcp.snd_buf) + len(kcp.snd_queue)
}
